﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace WpfStudy
{
    /// <summary>
    /// Window1.xaml 的交互逻辑
    /// </summary>
    public partial class Window1 : Window
    {
        Student student;
        Computer computer;

        public Window1()
        {
            InitializeComponent();

            BindingStudent();
            //一句话绑定
            //this.TBBanding.SetBinding(TextBox.TextProperty, new Binding("Name") { Source = student = new Student() });

            BindingStudentList();

            BindingAdd();

            BindingSlider();

            SetMultiBinding();

            PcNameBinding();
        }

        private void PcNameBinding()
        {
            computer = new Computer();
            computer.SetBinding(Computer.PCNameProperty, new Binding("Text") { Source = PcName1,UpdateSourceTrigger= UpdateSourceTrigger.PropertyChanged, Mode=BindingMode.TwoWay });
            Binding b1 = new Binding("PCName") { Source = computer };
            b1.NotifyOnTargetUpdated = true;
            b1.Mode = BindingMode.TwoWay;
            b1.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
            PcName2.SetBinding(TextBox.TextProperty, b1);
        }

        public void BindingSlider()
        {
            Binding binding = new Binding("Value") { Source = slider1 };
            binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;//当绑定目标的属性改变时，数据源的属性同步变化。
            RangeValidationRule rvr = new RangeValidationRule
            {
                ValidatesOnTargetUpdated = true//目标更新时也会校验。
            };
            binding.ValidationRules.Add(rvr);
            binding.StringFormat = "{0:F1}";
            binding.NotifyOnValidationError = true;
            Voice.SetBinding(TextBox.TextProperty, binding);

            Voice.AddHandler(Validation.ErrorEvent,
                             new RoutedEventHandler(ValidationError));
        }

        public void BindingStudent()
        {
            student = new Student();
            Binding binding = new Binding();
            binding.Source = student;
            binding.Path = new PropertyPath("Name");
            BindingOperations.SetBinding(TBBanding, TextBox.TextProperty, binding);
        }

        public void BindingStudentList()
        {
            //准备数据源
            List<Student> stuList = new List<Student>() {
                new Student(){ Id=0,Name="小红",Age=22},
                new Student(){ Id=1,Name="小绿卡",Age=25},
                new Student(){ Id=2,Name="是的",Age=23},
                new Student(){ Id=3,Name="元素",Age=29},
                new Student(){ Id=4,Name="奥利拉",Age=27},
            };

            listBoxStudents.ItemsSource = from stu in stuList where stu.Age >= 25 select stu;
            //注释后显示设置DataTemplate
            //this.listBoxStudents.DisplayMemberPath = "Name";

            TextId.SetBinding(TextBox.TextProperty, new Binding("SelectedItem.Id") { Source = this.listBoxStudents });
        }

        public void SetMultiBinding()
        {
            //准备bunding
            Binding b1 = new Binding("Text") { Source = userName1 };
            Binding b2 = new Binding("Text") { Source = userName2 };
            Binding b3 = new Binding("Text") { Source = userAge };

            //准备MultiBinding
            MultiBinding mb = new MultiBinding() { Mode = BindingMode.OneWay };
            mb.Bindings.Add(b1);
            mb.Bindings.Add(b2);
            mb.Bindings.Add(b3);

            mb.Converter = new LoginMultiBindingConvert();

            submitBtn.SetBinding(Button.IsEnabledProperty, mb);
        }

        public void BindingAdd()
        {
            //使用ObjectDataProvider对象进行绑定数据源的创建。
            ObjectDataProvider odp = new ObjectDataProvider();
            odp.ObjectInstance = new Calculator();
            odp.MethodName = "Add";
            odp.MethodParameters.Add("0");//是一个List，往里面可以加参数
            odp.MethodParameters.Add("0");

            //以ObjectDataProvider对象为Source创建Binding
            Binding bindingToArg1 = new Binding("MethodParameters[0]")
            {
                Source = odp,
                BindsDirectlyToSource = true,
                UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
            };
            Binding bindingToArg2 = new Binding("MethodParameters[1]")
            {
                Source = odp,
                BindsDirectlyToSource = true,
                UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
            };

            Binding bindingToResult = new Binding(".") { Source = odp };

            //将Binding关联到控件上
            TBArg1.SetBinding(TextBox.TextProperty, bindingToArg1);
            TBArg2.SetBinding(TextBox.TextProperty, bindingToArg2);
            TBResult.SetBinding(TextBox.TextProperty, bindingToResult);
        }


        private void BTShow_Click(object sender, RoutedEventArgs e)
        {
            string str = this.FindResource("MyString") as string;
            TB2.Text = str;
        }

        private void BandingBtn_Click(object sender, RoutedEventArgs e)
        {
            student.Name += "wuho~";
            Console.WriteLine(student.Name);
        }

        void ValidationError(object sender, RoutedEventArgs e)
        {
            if (Validation.GetErrors(Voice).Count > 0)
            {
                Voice.ToolTip = Validation.GetErrors(Voice)[0].ErrorContent.ToString();
            }
        }

        private void loadBtn_Click(object sender, RoutedEventArgs e)
        {
            List<Phone> phones = new List<Phone>()
            {
                new Phone(){Check=Check.confirm, Error=Error.Warning,Name="Xiao Mi8"},
                new Phone(){Check=Check.disconfirm, Error=Error.Warning,Name="Xiao Mi10Pro"},
                new Phone(){Check=Check.confirm, Error=Error.Electric,Name="OPPO"},
                new Phone(){Check=Check.suspect, Error=Error.Warning,Name="VIVO"},
            };

            phoneList.ItemsSource = phones;
        }

        private void saveBtn_Click(object sender, RoutedEventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            foreach (Phone p in phoneList.Items)
            {
                sb.Append($"Name={p.Name}\tError={p.Error}\tCheck={p.Check}\r\n");
            }
            using (StreamWriter sw = new StreamWriter(@"D:/gaobowen/phonesInfo.txt"))
            {
                sw.Write(sb.ToString());
            }
        }
    }

    internal class LoginMultiBindingConvert : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (!values.Cast<string>().Any(text => string.IsNullOrEmpty(text))
                && values[0].ToString() == values[1].ToString()
                && Int32.Parse(values[2].ToString()) > 20)
            {
                return true;
            }
            return false;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class Student : INotifyPropertyChanged
    {
        private string name = "";

        public event PropertyChangedEventHandler PropertyChanged;

        public string Name
        {
            get { return this.name; }
            set
            {
                this.name = value;
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));
                }

            }
        }
        public int Age { get; set; }
        public int Id { get; set; }
    }

    /// <summary>
    /// 数据校验实现类
    /// </summary>
    public class RangeValidationRule : ValidationRule
    {
        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            double d = 0;
            if (double.TryParse(value.ToString(), out d))
            {
                if (d >= 0 && d <= 10)
                {
                    //校验通过
                    return new ValidationResult(true, null);
                }
            }
            return new ValidationResult(false, "校验失败！");
        }
    }

    /// <summary>
    /// 手机肯能出现的问题，
    /// </summary>
    public enum Error
    {
        Warning,//系统报警
        Electric,//电力足
    }

    /// <summary>
    /// 检查确认
    /// </summary>
    public enum Check
    {
        confirm,//确认问题
        suspect,//怀疑存在问题
        disconfirm,//不存在问题
    }

    public class Phone
    {
        public Error Error { get; set; }
        public Check Check { get; set; }
        public string Name { get; set; }
    }

    /// <summary>
    /// 枚举转图片地址
    /// </summary>
    public class ErrorToSourceConvert : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Error error = (Error)value;
            switch (error)
            {
                case Error.Warning: return @"\Resource\image\Rep_device1.png";
                case Error.Electric: return @"\Resource\image\Rep_device3.png";
                default: return null;
            }
        }

        //Binding.Model为 oneway时不会被调用
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class CheckToNullableBoolConvert : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Check check = (Check)value;
            switch (check)
            {
                case Check.confirm: return true;
                case Check.disconfirm: return false;
                case Check.suspect:
                default: return null;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            bool? nb = (bool?)value;
            switch (nb)
            {
                case true: return Check.confirm;
                case false: return Check.disconfirm;
                case null:
                default: return Check.suspect;
            }
        }
    }

    /// <summary>
    /// Comoputer 添加依赖属性，并添加SetBinding方法
    /// </summary>
    public class Computer :DependencyObject
    {


        public string PCName
        {
            get { return (string)GetValue(PCNameProperty); }
            set { SetValue(PCNameProperty, value); }
        }

        // Using a DependencyProperty as the backing store for PCName.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PCNameProperty =
            DependencyProperty.Register("PCName", typeof(string), typeof(Computer));

        public BindingExpressionBase SetBinding(DependencyProperty dp,BindingBase binding)
        {
            return BindingOperations.SetBinding(this, dp, binding);
        }
                    
    }

}
